/*
* Open Source Physics software is free software as described near the bottom of this code file.
*
* For additional information and documentation on Open Source Physics please see:
* <http://www.opensourcephysics.org/>
*/
package org.opensourcephysics.display;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.ServiceUI;
import javax.print.SimpleDoc;
import javax.print.StreamPrintService;
import javax.print.StreamPrintServiceFactory;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Chromaticity;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.event.PrintJobAdapter;
import javax.print.event.PrintJobEvent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
/**
* Print utilities for OSP componets.
*
* @author Wolfgang Christian
* @version 1.0
*/
public class PrintUtils {
private PrintUtils() {}
// This method is like print() above but prints to a PostScript file
// instead of printing to a printer.
public static void saveComponentAsEPS(Component c) throws IOException {
// Find a factory object for printing Printable objects to PostScript.
DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
String format = "application/postscript"; //$NON-NLS-1$
StreamPrintServiceFactory factory = StreamPrintServiceFactory.lookupStreamPrintServiceFactories(flavor, format)[0];
// Ask the user to select a file and open the selected file
//JFileChooser chooser = new JFileChooser();
JFileChooser chooser = OSPRuntime.getChooser();
if(chooser.showSaveDialog(c)!=JFileChooser.APPROVE_OPTION) {
return;
}
File f = chooser.getSelectedFile();
FileOutputStream out = new FileOutputStream(f);
// Obtain a PrintService that prints to that file
StreamPrintService service = factory.getPrintService(out);
// Do the printing with the method below
printToService(c, service, null);
// And close the output file.
out.close();
}
public static void printComponent(Component c) {
// Get a list of all printers that can handle Printable objects.
DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
PrintService[] services = PrintServiceLookup.lookupPrintServices(flavor, null);
// Set some define printing attributes
PrintRequestAttributeSet printAttributes = new HashPrintRequestAttributeSet();
//printAttributes.add(OrientationRequested.LANDSCAPE); // landscape mode
printAttributes.add(OrientationRequested.PORTRAIT); // PORTRAIT mode
printAttributes.add(Chromaticity.MONOCHROME); // print in mono
printAttributes.add(javax.print.attribute.standard.PrintQuality.HIGH); // highest resolution
// Display a dialog that allows the user to select one of the
// available printers and to edit the default attributes
PrintService service = ServiceUI.printDialog(null, 100, 100, services, null, null, printAttributes);
// If the user canceled, don't do anything
if(service==null) {
return;
}
// Now call a method defined below to finish the printing
printToService(c, service, printAttributes);
}
public static void printToService(final Component c, PrintService service, PrintRequestAttributeSet printAttributes) {
Printable printable = new PrintableComponent(c);
DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
Doc doc = new SimpleDoc(printable, flavor, null);
DocPrintJob job = service.createPrintJob();
final JOptionPane pane = new JOptionPane(DisplayRes.getString("PrintUtils.Printing.Message"), JOptionPane.PLAIN_MESSAGE); //$NON-NLS-1$
JDialog dialog = pane.createDialog(c, DisplayRes.getString("PrintUtils.PrintDialog.Title")); //$NON-NLS-1$
// This listener object updates the dialog as the status changes
job.addPrintJobListener(new PrintJobAdapter() {
public void printJobCompleted(PrintJobEvent e) {
pane.setMessage(DisplayRes.getString("PrintUtils.PrintComplete.Message")); //$NON-NLS-1$
}
public void printDataTransferCompleted(PrintJobEvent e) {
pane.setMessage(DisplayRes.getString("PrintUtils.PrintTransferred.Message")); //$NON-NLS-1$
}
public void printJobRequiresAttention(PrintJobEvent e) {
pane.setMessage(DisplayRes.getString("PrintUtils.OutOfPaper.Message")); //$NON-NLS-1$
}
public void printJobFailed(PrintJobEvent e) {
pane.setMessage(DisplayRes.getString("PrintUtils.PrintFailed.Message")); //$NON-NLS-1$
}
});
// Show the dialog, non-modal.
dialog.setModal(false);
dialog.setVisible(true);
// Now print the Doc to the DocPrintJob
try {
job.print(doc, printAttributes);
} catch(PrintException e) {
// Display any errors to the dialog box
pane.setMessage(e.toString());
}
}
/*
* PrintableComponent copied from Java Examples in a Nutshell.
* Copyright (c) 2004 David Flanagan. All rights reserved.
* This code is from the book Java Examples in a Nutshell, 3nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose,
* including teaching and use in open-source projects.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book,
* please visit http://www.davidflanagan.com/javaexamples3.
*/
public static class PrintableComponent implements Printable {
Component c;
/**
* Constructor PrintableComponent
* @param c
*/
public PrintableComponent(Component c) {
this.c = c;
}
// This method should print the specified page number to the specified
// Graphics object, abiding by the specified page format.
// The printing system will call this method repeatedly to print all
// pages of the print job. If pagenum is greater than the last page,
// it should return NO_SUCH_PAGE to indicate that it is done. The
// printing system may call this method multiple times per page.
public int print(Graphics g, PageFormat format, int pagenum) {
// This implemenation is always a single page
if(pagenum>0) {
return Printable.NO_SUCH_PAGE;
}
// The Java 1.2 printing API passes us a Graphics object, but we
// can always cast it to a Graphics2D object
Graphics2D g2 = (Graphics2D) g;
// Translate to accomodate the requested top and left margins.
g2.translate(format.getImageableX(), format.getImageableY());
// Figure out how big the drawing is, and how big the page
// (excluding margins) is
Dimension size = c.getSize(); // component size
double pageWidth = format.getImageableWidth(); // Page width
double pageHeight = format.getImageableHeight(); // Page height
// If the component is too wide or tall for the page, scale it down
if(size.width>pageWidth) {
double factor = pageWidth/size.width; // How much to scale
g2.scale(factor, factor); // Adjust coordinate system
pageWidth /= factor; // Adjust page size up
pageHeight /= factor;
}
if(size.height>pageHeight) { // Do the same thing for height
double factor = pageHeight/size.height;
g2.scale(factor, factor);
pageWidth /= factor;
pageHeight /= factor;
}
// Now we know the component will fit on the page. Center it by
// translating as necessary.
g2.translate((pageWidth-size.width)/2, (pageHeight-size.height)/2);
// Draw a line around the outside of the drawing area and label it
g2.drawRect(-1, -1, size.width+2, size.height+2);
// Set a clipping region so the component can't draw outside of
// its won bounds.
g2.setClip(0, 0, size.width, size.height);
// Finally, print the component by calling its paint() method.
// This prints the background, border, and children as well.
// For swing components, if you don't want the background, border,
// and children, then call printComponent() instead.
c.paint(g);
// Tell the PrinterJob that the page number was valid
return Printable.PAGE_EXISTS;
}
}
}
/*
* Open Source Physics software is free software; you can redistribute
* it and/or modify it under the terms of the GNU General Public License (GPL) as
* published by the Free Software Foundation; either version 2 of the License,
* or(at your option) any later version.
* Code that uses any portion of the code in the org.opensourcephysics package
* or any subpackage (subdirectory) of this package must must also be be released
* under the GNU GPL license.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA
* or view the license online at http://www.gnu.org/copyleft/gpl.html
*
* Copyright (c) 2007 The Open Source Physics project
* http://www.opensourcephysics.org
*/